diff options
Diffstat (limited to 'app/[lng]/evcp/(evcp)/(procurement)/po/[id]/contract-detail-client.tsx')
| -rw-r--r-- | app/[lng]/evcp/(evcp)/(procurement)/po/[id]/contract-detail-client.tsx | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/app/[lng]/evcp/(evcp)/(procurement)/po/[id]/contract-detail-client.tsx b/app/[lng]/evcp/(evcp)/(procurement)/po/[id]/contract-detail-client.tsx new file mode 100644 index 00000000..28a85e50 --- /dev/null +++ b/app/[lng]/evcp/(evcp)/(procurement)/po/[id]/contract-detail-client.tsx @@ -0,0 +1,143 @@ +"use client" + +import * as React from "react" +import { Button } from "@/components/ui/button" +import { Badge } from "@/components/ui/badge" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { ChevronLeft } from "lucide-react" +import Link from "next/link" +import { toast } from "sonner" +import { saveSHIComment } from "@/lib/po/vendor-table/service" +import { useRouter } from "next/navigation" +import { ContractInfoCard } from "@/components/contract/contract-info-card" +import { ContractItemsCard } from "@/components/contract/contract-items-card" +import { Alert, AlertDescription } from "@/components/ui/alert" +import { AlertCircle } from "lucide-react" + +interface ContractDetailClientProps { + contract: any + lng: string +} + +export function ContractDetailClient({ contract, lng }: ContractDetailClientProps) { + const router = useRouter() + const [shiComment, setSHIComment] = React.useState(contract.shiComment || "") + const [isLoading, setIsLoading] = React.useState(false) + + const handleSaveComment = async () => { + try { + setIsLoading(true) + const result = await saveSHIComment(contract.id, shiComment) + if (result.success) { + toast.success(result.message) + router.refresh() + } else { + toast.error("의견 저장에 실패했습니다.") + } + } catch (error) { + toast.error("의견 저장 중 오류가 발생했습니다.") + } finally { + setIsLoading(false) + } + } + + return ( + <> + {/* 헤더 */} + <div className="flex items-center justify-between"> + <div className="flex items-center gap-4"> + <Link href={`/${lng}/evcp/po`}> + <Button variant="ghost" size="icon"> + <ChevronLeft className="h-5 w-5" /> + </Button> + </Link> + <div className="flex items-center gap-3"> + <h1 className="text-2xl font-bold tracking-tight">계약 상세</h1> + <div className="flex items-center gap-2"> + <span className="text-sm text-muted-foreground">계약번호:</span> + <span className="text-sm font-medium">{contract.contractNo}</span> + <Badge variant="outline" className="ml-2"> + {contract.status} + </Badge> + </div> + </div> + </div> + <div className="flex gap-2"> + <Button + variant="default" + onClick={handleSaveComment} + disabled={isLoading} + > + 의견저장 + </Button> + </div> + </div> + + {/* 계약 거절 사유 표시 (있는 경우) */} + {contract.rejectionReason && ( + <Alert variant="destructive"> + <AlertCircle className="h-4 w-4" /> + <AlertDescription> + <strong>계약 거절 사유:</strong> {contract.rejectionReason} + </AlertDescription> + </Alert> + )} + + {/* 계약 조건 */} + <ContractInfoCard contract={contract} /> + + {/* 코멘트 */} + <Card> + <CardHeader> + <CardTitle className="text-lg">코멘트</CardTitle> + </CardHeader> + <CardContent> + <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> + <div className="space-y-2"> + <label htmlFor="vendor-comment" className="text-sm font-medium text-muted-foreground"> + Vendor Comment + </label> + <div className="w-full min-h-[100px] px-3 py-2 text-sm border rounded-md bg-muted/50"> + {contract.vendorComment || "코멘트가 없습니다."} + </div> + </div> + <div className="space-y-2"> + <label htmlFor="shi-comment" className="text-sm font-medium"> + SHI Comment + </label> + <textarea + id="shi-comment" + className="w-full min-h-[100px] px-3 py-2 text-sm border rounded-md resize-none focus:outline-none focus:ring-2 focus:ring-ring" + placeholder="SHI 코멘트를 입력하세요..." + value={shiComment} + onChange={(e) => setSHIComment(e.target.value)} + /> + </div> + </div> + </CardContent> + </Card> + + {/* 계약문서 */} + <Card> + <CardHeader> + <CardTitle className="text-lg">계약문서</CardTitle> + </CardHeader> + <CardContent> + {contract.contractContent ? ( + <div className="prose prose-sm max-w-none"> + <pre className="whitespace-pre-wrap text-sm bg-muted/50 p-4 rounded-md"> + {contract.contractContent} + </pre> + </div> + ) : ( + <p className="text-sm text-muted-foreground">계약문서 내용이 없습니다.</p> + )} + </CardContent> + </Card> + + {/* 계약 품목 */} + <ContractItemsCard items={contract.items || []} currency={contract.currency} /> + </> + ) +} + |
